/**
 *******************************************************************************
 * @brief       Provide a brief description of the module here (Single line).
 * 
 * @author      Ashwin
 * 
 * @file        time.c
 * 
 * @version
 * 
 * @date        Feb 26, 2012 8:17:25 AM
 * 
 * @details     Provide a detailed description of the module here (Multi-line).
 * 
 * @pre         Mention any preconditions required to use this module.
 * 
 * @bug         List any bugs in this module.
 * 
 * @note        List any odd modes while using this module.
 * 
 * @warning     List any warnings against using the objects of this module.
 *******************************************************************************
 * @copyright 2012
 * <a href="http://www.afflatustech.com">Afflatus Techtronics</a>
 * and <a href="http://www.ashwinvijayakumar.co.nr">Ashwin Vijayakumar</a>
 * @n@n
 * This work is licensed under the Creative Commons
 * Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a copy
 * of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or
 * send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain
 * View, California, 94041, USA.
 *******************************************************************************
 */

/**@cond -----------------------------------------------------------------------
 * Includes section
 * Add all #include here.
 * ----------------------------------------------------------------- @endcond */

/**@cond System headers -------------------------------------------- @endcond */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/**@cond Local headers --------------------------------------------- @endcond */
#include "time.h"

/**@cond -----------------------------------------------------------------------
 * typedef section (File scope)
 * Add typedef's with file scope here.
 * Capitalization: Upper_Camel_Case.
 * Declare typedef's with project scope in time.h.
 * ----------------------------------------------------------------- @endcond */

/**@cond -----------------------------------------------------------------------
 * Constants section (File scope)
 * Add all constants with file scope here.
 * Capitalization: ALL_CAPS.
 * Note that all constants listed here are limited to this file scope.
 * For project wide scope, declare constants in time.h.
 * ----------------------------------------------------------------- @endcond */

/**@cond -----------------------------------------------------------------------
 * Macros section (File scope)
 * Add all macros with file scope here.
 * Capitalization: ALL_CAPS.
 * Note that all macros listed here are limited to this file scope.
 * For project wide scope, declare macros in time.h.
 * ----------------------------------------------------------------- @endcond */

#define HEX2ASCII(HEX_VALUE)            \
    do                                  \
    {                                   \
        HEX_VALUE &= 0x0F;              \
        if(HEX_VALUE >= 0x0A)           \
        {                               \
            HEX_VALUE += 0x37;          \
        }                               \
        else                            \
        {                               \
            HEX_VALUE += 0x30;          \
        }                               \
    } while(0)

/**@cond -----------------------------------------------------------------------
 * Global variables section (File scope)
 * Add global variables with file scope here. 
 * Capitalization: lower_case.
 * Declare them with 'static' keyword.
 * ----------------------------------------------------------------- @endcond */

/**@cond -----------------------------------------------------------------------
 * Global variables section (Project scope)
 * PROJECT SCOPE G-VARIABLES ARE LIKE FORBIDDEN FRUIT. REFRAIN FROM USING THEM, 
 * DECLARE FILE SCOPE G-VARIABLES INSTEAD AND DEFINE GETTER/SETTER METHODS TO 
 * ACCESS THEM.
 * Add global variables with project scope here. 
 * Capitalization: lower_case.
 * Declare them without 'static' keyword.
 * Also declare these variables in time.h with 'extern' keyword.
 * ----------------------------------------------------------------- @endcond */

static const rom char wday_name[7][4] = {
    {"Sun"}, {"Mon"}, {"Tue"}, {"Wed"}, {"Thu"}, {"Fri"}, {"Sat"}
};
static const rom char mon_name[12][4] = {
    {"Jan"}, {"Feb"}, {"Mar"}, {"Apr"}, {"May"}, {"Jun"},
        {"Jul"}, {"Aug"}, {"Sep"}, {"Oct"}, {"Nov"}, {"Dec"}
};

/**@cond -----------------------------------------------------------------------
 * Function prototypes section (File scope)
 * Add prototypes for all functions with file scope here. 
 * Capitalization: lower_Camel_Case.
 * Declare them with 'static' keyword.
 * For functions with project scope, declare the function prototype in 
 * time.h without 'static' keyword.
 * ----------------------------------------------------------------- @endcond */

/**@cond -----------------------------------------------------------------------
 * Getter/setter method section (Project scope)
 * Define getter/setter methods to provide project scope global access to file 
 * scope global variables. (AVOID USING THESE IF YOU HAVE THROUGHPUT ISSUES).
 * Capitalization: get_Camel_Case/is_Camel_Case/set_Camel_Case.
 * Declare the prototype for these functions in time.h. 
 * ----------------------------------------------------------------- @endcond */

/**@cond ***********************************************************************
 * TODO: Update all comment fields and delete this line.
 * MOD: For functions with project scope, remove 'static' keyword and declare
 * prototype in time.h
 * -------------------------------------------------------------------- @endcond
 * @fn          return_type function_name(TYPE parameter1, TYPE parameter2)
 * @return      Describe the function's return value here.
 * @param       parameter1 Describe the function's 1st parameter here.
 * @param       parameter2 Describe the function's 2nd parameter here.
 * @author      Ashwin
 * @date        Feb 26, 2012, 8:18:05 AM
 * @brief	Provide a brief description of the module here (Single line).
 * @details	Provide a detailed description of the module here (Multi-line).
 * @pre         Mention any preconditions required to use this function.
 * @post        Mention any postcondition required to use this function.
 * @bug         List any bugs in this module.
 * @note        List any odd modes while using this function.
 * @warning     List any warnings against using the objects of this function.
 *******************************************************************************
 */

char
*asctime(const struct tm *brokentime)
{
  static char retVal[26], *retValPtr;
  unsigned char len;

  memset(retVal, '0', strlen(retVal));

  /* Did not want to use memcpy series from C18 since it is broken */
  retValPtr = &retVal[0];

  len = 0;
  while(len < 3)
    {
      *retValPtr++ = wday_name[brokentime->tm_wday][len++];
    }

  *retValPtr++ = ' ';

  /* Did not want to use memcpy series from C18 since it is broken */
  len = 0;
  while(len < 3)
    {
      *retValPtr++ = mon_name[brokentime->tm_mon][len++];
    }

  retVal[7] = ' ';
  itoa(brokentime->tm_mday, &retVal[8]);
  retVal[10] = ' ';
  itoa(brokentime->tm_hour, &retVal[11]);
  retVal[13] = ':';
  itoa(brokentime->tm_min, &retVal[14]);
  retVal[16] = ':';
  itoa(brokentime->tm_sec, &retVal[17]);
  retVal[19] = ' ';
  itoa((1900 + brokentime->tm_year), &retVal[20]);
  retVal[24] = '\n';
  retVal[25] = '\0';

#if 0
  /*
   * Much simpler way of getting this done.
   * But it is slow, big and C18 shouts a 2066 warning.
   */
  sprintf(retVal, "%.3s %.3s%3d %.2d:%.2d:%.2d %d\n",
      wday_name[brokentime->tm_wday],
      mon_name[brokentime->tm_mon],
      brokentime->tm_mday, brokentime->tm_hour,
      brokentime->tm_min, brokentime->tm_sec,
      1900 + brokentime->tm_year);
#endif

  return(retVal);
}

/** End of function_name ************ Copyright (C) 2012 Afflatus Techtronics */

/**@cond ***********************************************************************
 * TODO: Update all comment fields and delete this line.
 * MOD: For functions with project scope, remove 'static' keyword and declare
 * prototype in time.h
 * -------------------------------------------------------------------- @endcond
 * @fn          return_type function_name(TYPE parameter1, TYPE parameter2)
 * @return      Describe the function's return value here.
 * @param       parameter1 Describe the function's 1st parameter here.
 * @param       parameter2 Describe the function's 2nd parameter here.
 * @author      Ashwin
 * @date        Feb 26, 2012, 10:03:12 AM
 * @brief	Provide a brief description of the module here (Single line).
 * @details	Provide a detailed description of the module here (Multi-line).
 * @pre         Mention any preconditions required to use this function.
 * @post        Mention any postcondition required to use this function.
 * @bug         List any bugs in this module.
 * @note        List any odd modes while using this function.
 * @warning     List any warnings against using the objects of this function.
 *******************************************************************************
 */

char
*asctime_r(const struct tm *brokentime, char *buffer)
{
  unsigned char len;

  /* Did not want to use memcpy series from C18 since it is broken */
  len = 0;
  while(len < 3)
      {
        *buffer++ = wday_name[brokentime->tm_wday][len++];
      }

  *buffer++ = ' ';

  /* Did not want to use memcpy series from C18 since it is broken */
  len = 0;
  while(len < 3)
      {
        *buffer++ = mon_name[brokentime->tm_mon][len++];
      }

  *buffer++ = ' ';

  time_itoa(brokentime->tm_mday, buffer, 2);
  buffer += 2;
  *buffer++ = ' ';
  time_itoa(brokentime->tm_hour, buffer, 2);
  buffer += 2;
  *buffer++ = ':';
  time_itoa(brokentime->tm_min, buffer, 2);
  buffer += 2;
  *buffer++ = ':';
  time_itoa(brokentime->tm_sec, buffer, 2);
  buffer += 2;
  *buffer++ = ' ';
#if 0
  /* Put 2000 instead of 1900 as base to support DS1307/1629 year reg format */
  time_itoa((1900 + brokentime->tm_year), buffer, 4);
#endif
  time_itoa((2000 + brokentime->tm_year), buffer, 4);
  buffer += 4;
  *buffer++ = '\n';
  *buffer++ = '\0';

#if 0
  /*
   * Much simpler way of getting this done.
   * But it is slow, big and C18 shouts a 2066 warning.
   */
  sprintf(buffer, "%.2d %.2d:%.2d:%.2d %d\n",
      brokentime->tm_mday,
      brokentime->tm_hour,
      brokentime->tm_min,
      brokentime->tm_sec,
      1900 + brokentime->tm_year);
#endif
  return(buffer);
}

/** End of function_name ************ Copyright (C) 2012 Afflatus Techtronics */

/**@cond ***********************************************************************
 * TODO: Update all comment fields and delete this line.
 * MOD: For functions with project scope, remove 'static' keyword and declare
 * prototype in time.h
 * -------------------------------------------------------------------- @endcond
 * @fn          void function_name(TYPE parameter1, TYPE parameter2)
 * @return      Describe the function's return value here.
 * @param       parameter1 Describe the function's 1st parameter here.
 * @param       parameter2 Describe the function's 2nd parameter here.
 * @author      Ashwin
 * @date        Feb 27, 2012, 8:42:49 PM
 * @brief	Provide a brief description of the module here (Single line).
 * @details	Provide a detailed description of the module here (Multi-line).
 * @pre         Mention any preconditions required to use this function.
 * @post        Mention any postcondition required to use this function.
 * @bug         List any bugs in this module.
 * @note        List any odd modes while using this function.
 * @warning     List any warnings against using the objects of this function.
 *******************************************************************************
 */

void
time_itoa(int value, char* str, int len)
{
  char *strBuf, *lenBuf, buf;
  int sign, ctr = 0;

  sign = 1;
  strBuf = str;
  lenBuf = str + len;

  if (value < 0)
    {
      sign = -1;      /* don't negate the whole number now - do it digit by digit */
    }

  do
    {
      *strBuf++ = sign*(value % 10) + '0';  /* create a double negative when (value % 10) < 0 */
      ctr++;
    } while ((value /= 10) != 0);    /* note change from '>' to '!=' - value must remain negative without terminating the loop */

  while ( strBuf < lenBuf )
    {
      *strBuf++ = '0';
      ctr++;
    }

  if (sign == -1)
    {
      *strBuf++ = '-';
      ctr++;
    }

  lenBuf = str + (ctr - 1);

  while(lenBuf > str)
    {
      buf = *str;
      *str++ = *lenBuf;
      *lenBuf-- = buf;
    }

  *strBuf = '\0';
}

/** End of function_name ************ Copyright (C) 2012 Afflatus Techtronics */

/** END OF FILE ********************* Copyright (C) 2012 Afflatus Techtronics */
